package cn.enilu.flash.api.controller.h5;

import cn.enilu.flash.api.utils.BaiduMapUtils;
import cn.enilu.flash.bean.dto.HelpTaskDto;
import cn.enilu.flash.bean.dto.ProofDto;
import cn.enilu.flash.bean.dto.TaskProofDto;
import cn.enilu.flash.bean.dto.TaskStepDto;
import cn.enilu.flash.bean.entity.order.PayOrder;
import cn.enilu.flash.bean.entity.system.Cfg;
import cn.enilu.flash.bean.entity.system.User;
import cn.enilu.flash.bean.entity.task.HelpTask;
import cn.enilu.flash.bean.entity.task.MoneyInfo;
import cn.enilu.flash.bean.entity.task.Proof;
import cn.enilu.flash.bean.entity.task.TaskStep;
import cn.enilu.flash.bean.enumeration.ConfigKeyEnum;
import cn.enilu.flash.bean.vo.front.Ret;
import cn.enilu.flash.bean.vo.front.Rets;
import cn.enilu.flash.bean.vo.query.SearchFilter;
import cn.enilu.flash.bean.vo.task.HelpTaskDetailVo;
import cn.enilu.flash.bean.vo.task.HelpTaskListVo;
import cn.enilu.flash.bean.vo.task.TaskStepVo;
import cn.enilu.flash.security.JwtUtil;
import cn.enilu.flash.service.order.PayOrderService;
import cn.enilu.flash.service.order.TaskOrderService;
import cn.enilu.flash.service.system.CfgService;
import cn.enilu.flash.service.system.UserService;
import cn.enilu.flash.service.task.*;
import cn.enilu.flash.utils.HttpUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import java.math.BigDecimal;
import java.util.*;

@RestController
@RequestMapping("/h5/task")
@Transactional
@Api(tags = "任务相关接口")
public class H5HelpTaskController {
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private CfgService cfgService;
    @Autowired
    private HelpTaskService helpTaskService;
    @Autowired
    private TaskStepService taskStepService;
    @Autowired
    private ProofService proofService;
    @Autowired
    private TaskOrderService taskOrderService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private UserService userService;
    @Autowired
    private ClassifyService classifyService;
    @Autowired
    private MoneyInfoService moneyInfoService;

    @GetMapping("/getCost")
    @ApiOperation("获取费用 \n" +
            "return rate费率；totalServiceFee总服务费；totalCost：总费用")
    public Ret getCost(@ApiParam("任务单价") BigDecimal price,@ApiParam("任务数量") Integer num){
        User user = userService.get(JwtUtil.getUserId());
        Map<String,Object> map = new LinkedHashMap<>();
        BigDecimal serviceFee = null;
        if(user.getIsVip() != null && user.getIsVip()==1 && user.getVipExpirationDate()!=null && user.getVipExpirationDate().getTime()>new Date().getTime()){// 如果是Vip用户
            Cfg VIP_SERVICE_CHARGE = cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, ConfigKeyEnum.VIP_SERVICE_CHARGE.getValue()));
            String cfgValue = VIP_SERVICE_CHARGE.getCfgValue();
            serviceFee  = price.multiply(new BigDecimal(cfgValue));
            Double v = Double.valueOf(cfgValue)*100;
            map.put("rate",v.intValue()+"%");
        }else {
            Cfg SERVICE_CHARGE = cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, ConfigKeyEnum.SERVICE_CHARGE.getValue()));
            String cfgValue = SERVICE_CHARGE.getCfgValue();
            serviceFee  = price.multiply(new BigDecimal(cfgValue));
            Double v = Double.valueOf(cfgValue)*100;
            map.put("rate",v.intValue()+"%");
        }
        BigDecimal totalServiceFee = serviceFee.multiply(new BigDecimal(num)); // 总服务费
        map.put("totalServiceFee",totalServiceFee);
        BigDecimal brokerage = price.multiply(new BigDecimal(num));   // 总任务佣金
        BigDecimal totalCost = brokerage.add(totalServiceFee);
        map.put("totalCost",totalCost);
        return Rets.success(map);
    }
    /**
     * 发布任务活动
     * @param helpTaskDto
     * @return
     */
    @PostMapping("/add")
    @ApiOperation("发布任务接口：\n " +
            "classifyId：分类id  " +
            "title：标题  " +
            "num：数量 " +
            "sketch：任务简述 " +
            "price:单价 " +
            "timeLimit 完成时限（小时）" +
            "endTime 结束时间 " +
            "cityId 城市id " +
            "taskStepList[0].stepExplain 步骤说明 " +
            "taskStepList[0].idFiles 步骤图片id，多图片用英文,隔开 " +
            "taskProofList[0].name 凭证名称 " +
            "taskProofList[0].type 凭证类型：1文字，2图片 " +
            "")
    public Ret addHelpTask(@RequestBody HelpTaskDto helpTaskDto){
        HelpTask task = null;
        User user = userService.get(JwtUtil.getUserId());
        try {
            task = new HelpTask();
            BeanUtils.copyProperties(helpTaskDto,task);
            task.setId(null);
            task.setCreateTime(new Date());
            task.setLastNum(task.getNum());
            task.setCreateBy(JwtUtil.getUserId());
            if(user.getIsVip()==null || user.getIsVip() == 0 || user.getVipExpirationDate() == null || user.getVipExpirationDate().getTime()<new Date().getTime()){// 普通会员
                Double serviceCharge = Double.valueOf(cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, ConfigKeyEnum.SERVICE_CHARGE.getValue())).getCfgValue());
                task.setServiceFee(task.getPrice().multiply(new BigDecimal(serviceCharge)));// 单笔服务费
            }else {
                Double vipServiceCharge = Double.valueOf(cfgService.get(new SearchFilter("cfgName", SearchFilter.Operator.EQ, ConfigKeyEnum.VIP_SERVICE_CHARGE.getValue())).getCfgValue());
                task.setServiceFee(task.getPrice().multiply(new BigDecimal(vipServiceCharge)));// 单笔服务费
            }
            task.setState(0);// 待支付
            if(task.getCityId()==null){
                String ip = HttpUtil.getIp();
                if(ip.equals("127.0.0.1") || ip.equals("0:0:0:0:0:0:0:1")){
                    ip = "219.159.239.17";// 设为崇左
                }
                Integer cityCode = BaiduMapUtils.getCityCode(ip);
                task.setCityId(cityCode);
            }
            task = helpTaskService.insert(task);
            if(task==null) throw new RuntimeException();
            update(helpTaskDto,task.getId());
        } catch (RuntimeException e) {
            e.printStackTrace();
            return Rets.failure("发布失败！");
        }
        return Rets.success(task.getId());
    }
    /**
    * @author: 韦武朝
    * @date: 2022/4/3 21:38
    * @param taskId: 任务id
    */
    @GetMapping("/getTaskDetail")
    @ApiOperation("获取任务详情")
    public Ret getTaskDetail(@ApiParam("任务id") Long taskId){
        if(taskId == null){
            return Rets.failure("任务不存在！");
        }
        HelpTask helpTask = helpTaskService.get(taskId);
        if(helpTask == null){
            return Rets.failure("任务不存在！");
        }
        HelpTaskDetailVo detailVo = new HelpTaskDetailVo();
        BeanUtils.copyProperties(helpTask,detailVo);
        List<TaskStep> taskSteps = taskStepService.queryAll(new SearchFilter("taskId", SearchFilter.Operator.EQ,helpTask.getId()));
        List<TaskStepVo> taskStepVoList = new ArrayList<>();
        for(TaskStep taskStep:taskSteps){
            TaskStepVo vo = new TaskStepVo();
            BeanUtils.copyProperties(taskStep,vo);
            taskStepVoList.add(vo);
        }
        detailVo.setTaskStepList(taskStepVoList);
        List<Proof> proofList = proofService.queryAll(new SearchFilter("taskId", SearchFilter.Operator.EQ, taskId));
        List<ProofDto> proofDtos = new ArrayList<>();
        for(Proof proof:proofList){
            ProofDto proofDto = new ProofDto();
            BeanUtils.copyProperties(proof,proofDto);
            proofDtos.add(proofDto);
        }
        detailVo.setProofList(proofDtos);
        return Rets.success(detailVo);
    }
    /**
     * 修改任务
     * 仅供修改 完成时限（timeLimit）
     * 任务结束时间（endTime）
     * 百度city_code（cityId）
     * 任务简述（sketch）
     * 标题（title）
     * 分类（classifyId）
     * @param helpTaskDto
     * @return
     */
    @PostMapping("/edit")
    @ApiOperation("修改任务 \n " +
            "id 任务id " +
            "classifyId：分类id  " +
            "title：标题  " +
            "num：数量（不允许修改） " +
            "sketch：任务简述 " +
            "price:单价（不允许修改） " +
            "timeLimit 完成时限（小时）" +
            "endTime 结束时间 " +
            "cityId 城市id " +
            "taskStepList[0].stepExplain 步骤说明 " +
            "taskStepList[0].idFiles 步骤图片id，多图片用英文,隔开 " +
            "taskProofList[0].name 凭证名称 " +
            "taskProofList[0].type 凭证类型：1文字，2图片 " +
            "taskProofList[0].content 凭证内容，当type=1时为文字，当type=2时为图片id,多个图片id用英文,隔开" +
            "")
    public Ret editHelpTask(@RequestBody HelpTaskDto helpTaskDto){
        try {
            if(helpTaskDto.getId()==null){
                logger.error("任务id不能为空！");
                return Rets.failure("修改失败！");
            }
            HelpTask task = helpTaskService.get(helpTaskDto.getId());
            if(task.getNum().intValue()!=helpTaskDto.getNum().intValue() || task.getPrice().compareTo(helpTaskDto.getPrice())!=0){
                return Rets.failure("单价和发布数量不允许修改哦~");
            }
            SearchFilter idSearchFilter = new SearchFilter("taskId", SearchFilter.Operator.EQ,helpTaskDto.getId());
            List<TaskStep> taskSteps = taskStepService.queryAll(idSearchFilter);
            List<Long> ids = new ArrayList<>();
            for(TaskStep taskStep:taskSteps){
                ids.add(taskStep.getId());
            }
            taskStepService.delete(ids); // 删除所有id
            ids = new ArrayList<>();
            List<Proof> proofs = proofService.queryAll(idSearchFilter);
            for(Proof proof:proofs){
                ids.add(proof.getId());
            }
            proofService.delete(ids);
            task.setModifyBy(JwtUtil.getUserId());
            task.setModifyTime(new Date());
            task.setEndTime(helpTaskDto.getEndTime());
            task.setTimeLimit(helpTaskDto.getTimeLimit());
            task.setCityId(helpTaskDto.getCityId());
            task.setSketch(helpTaskDto.getSketch());
            task.setClassifyId(helpTaskDto.getClassifyId());
            task.setTitle(helpTaskDto.getTitle());
            if(task.getState()!=0){
                task.setState(2);
            }
            task = helpTaskService.update(task);
            update(helpTaskDto,task.getId());
        } catch (Exception e) {
            logger.error(e.toString());
            return Rets.failure("修改失败！");
        }
        return Rets.success(helpTaskDto.getId());
    }

    /**
     * 设置任务状态
     * @param taskId 任务id
     * @param state 1进行中，2审核中，3待修改，5已结束，6暂停中
     * @return
     */
    @ApiOperation("设置状态")
    @GetMapping("/setState")
    @Transactional
    public Ret setState(@ApiParam("任务ID") Long taskId,@ApiParam("1进行中，2审核中，3待修改，5已结束，6暂停中") Integer state){
        User user = userService.get(JwtUtil.getUserId());
        if(taskId == null){
            return Rets.failure("修改任务状态失败：-1");
        }
        HelpTask helpTask = helpTaskService.get(taskId);
        if(helpTask.getCreateBy() != user.getId()){
            return Rets.failure("只能操作自己发布的任务哦~");
        }
        if(helpTask.getState() == state){
            return Rets.success();
        }
        if(state == 1){ // 设置进行中
            if(helpTask.getState()!=6) return Rets.failure("任务开始失败！"); // 只能由暂停到进行中
            helpTask.setState(1);
        }else if(state == 6){ // 暂停任务
            if(helpTask.getState()!=1) return Rets.failure("任务暂停失败！"); // 只能由进行中到暂停
            helpTask.setState(6);
        }else if(state == 5){ // 结束任务
            List<SearchFilter> searchFilterList = new ArrayList<>();// 筛选此任务的订单
            searchFilterList.add(new SearchFilter("taskId", SearchFilter.Operator.EQ,taskId));
            List<Integer> states = new ArrayList<>();
            states.add(3); // 已完成
            states.add(7); // 已取消
            searchFilterList.add(new SearchFilter("state", SearchFilter.Operator.NOTIN,states)); // 不是 已完成或已取消 的订单
            long count = taskOrderService.count(searchFilterList);
            if(count>0){
                return Rets.failure("您的任务还有未完成任务订单，可先暂停任务！");
            }
            helpTask.setState(5);
            PayOrder payOrder = payOrderService.get(new SearchFilter("taskId", SearchFilter.Operator.EQ, taskId));
            if(payOrder!=null && helpTask.getLastNum()>0){  // 存在付款订单 且 有任务剩余
                // 退钱业务
                BigDecimal price = helpTask.getPrice(); // 单价
                BigDecimal serviceFee = helpTask.getServiceFee(); // 单任务服务费
                Integer lastNum = helpTask.getLastNum(); // 剩余份数
                // 计算要退的钱
                BigDecimal add = price.add(serviceFee); // 单个任务所需退的钱
                BigDecimal refundAmount = add.multiply(new BigDecimal(lastNum)); // 退款金额
                MoneyInfo moneyInfo = moneyInfoService.setMoneyInfo(taskId, JwtUtil.getUserId(), 4, refundAmount);
                if(moneyInfo== null){
                    throw new RuntimeException("任务结束失败！");
                }
            }
        }
        helpTaskService.update(helpTask); // 设置状态
        return Rets.success();
    }

    /**
     * 获取我发布的帮忙任务列表
     * @param page
     * @param limit
     * @param state 状态:0待支付，1进行中，2审核中，3待修改，5已结束，6暂停中
     * @return
     */
    @GetMapping("/getMyHelpTask")
    public Ret getMyHelpTask(
            @RequestParam(defaultValue = "1") Integer page,
            @RequestParam(defaultValue = "10") Integer limit,
            @RequestParam(defaultValue = "-1") Integer state
    ){
        StringBuffer sql = new StringBuffer(" Select * from t_help_task where 1=1 ");
        if(state != -1){
            sql.append(" and state = "+state);
        }
        sql.append(" and create_by = "+JwtUtil.getUserId());
        if(page<1) page = 1;
        int start = (page-1)*limit;
        sql.append(" LIMIT "+start+","+limit+" ");
        List<HelpTask> tasks = helpTaskService.queryBySql(sql.toString());
        List<HelpTaskListVo> taskVoList = new ArrayList<>();
        for(HelpTask helpTask:tasks){
            HelpTaskListVo HelpTaskListVo = new HelpTaskListVo();
            BeanUtils.copyProperties(helpTask,HelpTaskListVo);
            taskVoList.add(HelpTaskListVo);
        }
        return Rets.success(taskVoList);
    }

    private void update(HelpTaskDto helpTaskDto,Long taskId){
        List<TaskStepDto> taskStepList = helpTaskDto.getTaskStepList();
        for(TaskStepDto taskStepDto:taskStepList){
            TaskStep taskStep = new TaskStep();
            BeanUtils.copyProperties(taskStepDto,taskStep);
            taskStep.setCreateBy(JwtUtil.getUserId());
            taskStep.setTaskId(taskId);
            taskStep.setId(null);
            taskStep.setCreateTime(new Date());
            TaskStep insert = taskStepService.insert(taskStep);
            if(insert==null) throw new RuntimeException();
        }

        List<TaskProofDto> taskProofList = helpTaskDto.getTaskProofList();
        for(TaskProofDto dto:taskProofList){
            Proof proof = new Proof();
            BeanUtils.copyProperties(dto,proof);
            proof.setId(null);
            proof.setTaskId(taskId);
            proof.setCreateBy(JwtUtil.getUserId());
            proof.setCreateTime(new Date());
            Proof insert = proofService.insert(proof);
            if(insert==null) throw new RuntimeException();
        }
    }
}
